/******************************************************************************\
**  filename:   zcom_uiTextDialog.c
**  author:     tianjun
**  created:    2007-12-13 9:51:33
\******************************************************************************/
#include <pwin.h>
#include <display.h>
#include "zcom_uiTextDialog.h"

enum
{
    SCROLL_NA,
    SCROLL_UP,
    SCROLL_DOWN
};

static struct
{
    char *String;
    unsigned Length;

    int iPageTopLinePos;
    int eScrollAction;

    softKeySelectCB PositiveSelectCB;
    void *PositiveSelectCBArg;

    softKeySelectCB NegativeSelectCB;
    void *NegativeSelectCBArg;

} zcom_uiTextDialogS;

static
void zcom_uiTextDialogScrollDown(UIMenu *menu, Pw_Event *ev)
{
    // Go to the next line
    //
    zcom_uiTextDialogS.eScrollAction = SCROLL_DOWN;

    Pw_WindowRepaint(Pw_EventGetWindow(ev));
}

static
void zcom_uiTextDialogScrollUp(UIMenu *menu, Pw_Event *ev)
{
    // Go to the previous line
    //
    zcom_uiTextDialogS.eScrollAction = SCROLL_UP;

    Pw_WindowRepaint(Pw_EventGetWindow(ev));
}

static
Pw_Bool zcom_uiTextDialogEvents(UIMenu *menu, Pw_Event *ev)
{
    if (Pw_EventGetType(ev) == Pw_KeyPressEventType)
    {
        Pw_uInt keycode = Pw_KeyEventGetKeyCode(Pw_EventCastToKeyEvent(ev));

        switch (keycode)
        {
        case KEYSYM_END:
            uiMainWinKeyEnd();
            break;

         case KEYSYM_DOWN:
            zcom_uiTextDialogScrollDown(menu, ev);
            break;

         case KEYSYM_UP:
            zcom_uiTextDialogScrollUp(menu, ev);
            break;

        case KEYSYM_SOFT_POSITIVE:
            if (zcom_uiTextDialogS.PositiveSelectCB != NULL)
            {
                zcom_uiTextDialogS.PositiveSelectCB(zcom_uiTextDialogS.PositiveSelectCBArg);
            }
            break;

        case KEYSYM_SOFT_NEGATIVE:
            if (zcom_uiTextDialogS.NegativeSelectCB != NULL)
            {
                zcom_uiTextDialogS.NegativeSelectCB(zcom_uiTextDialogS.NegativeSelectCBArg);
            }
            break;

        default:
            break;
        }
    }

    return TRUE;
}

static
void zcom_uiTextDialogRepaint(
    UIMenu *menu,
    Pw_GC *gc,
    Pw_Coord y0,
    Pw_Coord y1
)
{
    Pw_Coord    w, h;
    Pw_Coord    Line_y0;
    Pw_Coord    sb_w, sb_y0, sb_y1;

    Pw_WindowGetSize(Pw_GCGetWindow(gc), &w, &h);
    Pw_GCSetFont(gc, dispFontGet(DISP_FONT_TYPE_REGULAR));

    Line_y0 = y0;
    sb_w = w; sb_y0 = y0; sb_y1 = y1;
    w -= CFG_SCROLL_BAR_WIDTH;

    int nLines = 0;
    int nPageLines = (y1 - y0) / Pw_GCGetFontHeight(gc);
    int iCurrentLine = 0;
    int iPreviousLinePos = -1;  // must be a negative, or must less than zero(0).
    int iNextLinePos = 0;

    //
    // Compute the current position and the current line
    //
    for (int i = 0; i < zcom_uiTextDialogS.Length; )
    {
        int nLineBytes = Pw_GCStringFit(gc, &zcom_uiTextDialogS.String[i], w);
        if (nLineBytes <= 0)
        {
            debugf("[zcom_uiTextDialogRepaint] nLineBytes <= 0\n");
            break;
        }

        iNextLinePos = i + nLineBytes;

        if (i < zcom_uiTextDialogS.iPageTopLinePos)
        {
            iCurrentLine++;
            iPreviousLinePos = i;
        }
        else if (zcom_uiTextDialogS.iPageTopLinePos < iNextLinePos)
        {
            int eScrollAction = zcom_uiTextDialogS.eScrollAction;
            zcom_uiTextDialogS.eScrollAction = SCROLL_NA;

            switch (eScrollAction)
            {
            case SCROLL_NA:
                // keep zcom_uiTextDialogS.iPageTopLinePos
                break;
            case SCROLL_UP:
                zcom_uiTextDialogS.iPageTopLinePos = iPreviousLinePos;
                iCurrentLine--;
                iPreviousLinePos = -1;
                break;
            case SCROLL_DOWN:
                iPreviousLinePos = zcom_uiTextDialogS.iPageTopLinePos;
                zcom_uiTextDialogS.iPageTopLinePos = iNextLinePos;
                iCurrentLine++;
                break;
            default:
                debugf("[zcom_uiTextDialogRepaint] invalid eScrollAction\n");
                return;
            }
        }

        nLines++;
        i += nLineBytes;
    }

    //
    // Adjust the current position and the current line
    //
    if (iCurrentLine + nPageLines - 2 > nLines) //leave 2 line
    {
        zcom_uiTextDialogS.iPageTopLinePos = iPreviousLinePos;
        iCurrentLine--;
        iPreviousLinePos = -1; // set it invalid
    }

    if ((iCurrentLine < 0) ||
        (zcom_uiTextDialogS.iPageTopLinePos < 0))
    {
        zcom_uiTextDialogS.iPageTopLinePos = 0;
        iCurrentLine = 0;
        iPreviousLinePos = -1; // set it invalid
    }

//    printf("________________________________________________\n");
//    printf("nLines = 0x%X\n", nLines);
//    printf("nPageLines = 0x%X\n", nPageLines);
//    printf("iCurrentLine = 0x%X\n", iCurrentLine);
//    printf("iPreviousLinePos = 0x%X\n", iPreviousLinePos);

    //
    // Draw Scroll Bar
    //
    if (nLines <= nPageLines)
    {
        uiMenuScrollBarDraw(
            gc,
            sb_w,
            sb_y0,
            sb_y1,
            1,
            1
            );
    }
    else
    {
        uiMenuScrollBarDraw(
            gc,
            sb_w,
            sb_y0,
            sb_y1,
            iCurrentLine,
            nLines - nPageLines + 1
            );
    }

    //
    // Draw Text String
    //
    for (int i = zcom_uiTextDialogS.iPageTopLinePos; i < zcom_uiTextDialogS.Length; )
    {
        int nLineBytes = Pw_GCStringFit(gc, &zcom_uiTextDialogS.String[i], w);
        if (nLineBytes <= 0)
        {
            debugf("[zcom_uiTextDialogRepaint] nLineBytes <= 0\n");
            break;
        }

        Line_y0 += Pw_GCGetFontHeight(gc);
        if (Line_y0 > y1)
        {
            debugf("[zcom_uiTextDialogRepaint] Screen Overflow\n");
            break;
        }

        Pw_DrawStringNAnchor(
            gc,
            0,
            Line_y0,
            &zcom_uiTextDialogS.String[i],
            nLineBytes,
            Pw_TextAnchor_BotLeft
            );

        i += nLineBytes;
    }
}

static
void zcom_uiTextDialogStart(
    UIMenuText *Title,
    LangIdx PositiveIdx,
    LangIdx NegativeIdx
)
{
    UIMenuUserInit init = {};

    init.title  = *Title;

    init.eventHandler   = zcom_uiTextDialogEvents;
    init.repaintHandler = zcom_uiTextDialogRepaint;

    uiMenuSoftKeyPositive(init.softKey, PositiveIdx);
    uiMenuSoftKeyNegative(init.softKey, NegativeIdx);

    uiMenuUserInit(&init, NULL);
}

void zcom_uiTextDialogInit(
    char *String,   // String must be a static parameter
    unsigned Length,
    UIMenuText *Title,
    SoftKeyParameter *PositiveParam,
    SoftKeyParameter *NegativeParam
)
{
    memset(&zcom_uiTextDialogS, 0, sizeof(zcom_uiTextDialogS));
    zcom_uiTextDialogS.String = String;
    zcom_uiTextDialogS.Length = Length;
    zcom_uiTextDialogS.PositiveSelectCB    = PositiveParam->selectCB;
    zcom_uiTextDialogS.PositiveSelectCBArg = PositiveParam->selectCBArg;
    zcom_uiTextDialogS.NegativeSelectCB    = NegativeParam->selectCB;
    zcom_uiTextDialogS.NegativeSelectCBArg = NegativeParam->selectCBArg;

    zcom_uiTextDialogStart(
        Title,
        PositiveParam->textIdx,
        NegativeParam->textIdx
        );
}

/*
//
// Sample Code
//
#include "zcom_uiTextDialog.h"
#define TEST_STRING "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"
static void zcom_uiTextDialogTest(void *arg)
{
    UIMenuText Title = {
        .textIdx   = LANG_Zcom_Menu_Main_title,
        .textCB    = NULL,
        .textCBarg = NULL,
    };

    SoftKeyParameter PositiveParam = {
        .textIdx     = LANG_SoftKey_Select,
        .selectCB    = NULL,
        .selectCBArg = NULL
    };

    SoftKeyParameter NegativeParam = {
        .textIdx     = LANG_SoftKey_Back,
        .selectCB    = NULL,
        .selectCBArg = NULL
    };

    zcom_uiTextDialogInit(
        TEST_STRING,
        strlen(TEST_STRING),
        &Title,
        &PositiveParam,
        &NegativeParam
        );
}
*/
